package cn.gs.timer.server;

import cn.gs.common.interfaces.ITimerListener;
import cn.gs.exception.ConfigException;
import cn.gs.util.ObjectToXMLUtil;
import java.io.File;
import java.rmi.RemoteException;
import java.util.Map.Entry;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/*
 * @author gs
 */
public class TimerThread extends TimerTask {

    private int ordinal = 0;

    @Override
    public void run() {
        ordinal++;
        if (ordinal >= setting.timeCount) {
            ordinal = 0;
            setting.now++;
            ObjectToXMLUtil util = new ObjectToXMLUtil();
            util.objectXmlEncoder(setting, "day.xml");
            newDay(setting.now);
        }
        timer(ordinal);
    }

    public static class Setting {

        private int now;
        private int timeSpan;
        private int timeCount;

        public int getNow() {
            return now;
        }

        public void setNow(int now) {
            this.now = now;
        }

        public int getTimeSpan() {
            return timeSpan;
        }

        public void setTimeSpan(int timeSpan) {
            this.timeSpan = timeSpan;
        }

        public int getTimeCount() {
            return timeCount;
        }

        public void setTimeCount(int timeCount) {
            this.timeCount = timeCount;
        }
    }
    Timer timer;
    Setting setting;
    private Map<String, ITimerListener> listeners = new HashMap<>();

    public boolean init() {
        ObjectToXMLUtil util = new ObjectToXMLUtil();
        File file = new File("day.xml");
        if (file.exists()) {
            timer = new Timer(true);
            setting = (Setting) util.objectXmlDecoder(file.getAbsolutePath());
            updateTimer();
            Logger.getLogger(TimerThread.class.getName()).log(Level.SEVERE, "TimerThread Started.");
            return true;
        }
        Logger.getLogger(TimerThread.class.getName()).log(Level.SEVERE, "TimerThread init failed by Day Setting File Undefined.");
        return false;
    }

    public void timer(int ordinal) {
        Logger.getLogger(TimerThread.class.getName()).log(Level.CONFIG, "Timer: " + ordinal + " @ " + setting.now);
        for (ITimerListener i : listeners.values()) {
            try {
                i.timer(ordinal);
            } catch (RemoteException ex) {
                Logger.getLogger(TimerThread.class.getName()).log(Level.WARNING, null, ex);
            }
        }
    }

    public void newDay(int day) {
        Logger.getLogger(TimerThread.class.getName()).log(Level.INFO, "A NEW DAY. " + setting.now);
        Iterator<Entry<String, ITimerListener>> i = listeners.entrySet().iterator();
        while (i.hasNext()) {
            Entry<String, ITimerListener> e = i.next();
            try {
                e.getValue().newDay(day);
            } catch (RemoteException ex) {
                Logger.getLogger(TimerThread.class.getName()).log(Level.WARNING, "DISCONNECT TO " + e.getKey(), ex);
                i.remove();
            }
        }
    }

    void updateTimer() {
        Logger.getLogger(TimerThread.class.getName()).log(Level.INFO, "Timer updated by span being changed to " + setting.timeSpan);
        timer.schedule(this, 5000, setting.timeSpan);
    }

    public void registerServer(String server, ITimerListener listener) {
        listeners.put(server, listener);
    }

    public void removeServer(String server) {
        listeners.remove(server);
    }
}
